package cn.sc.summer.core.util.mail;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.sc.summer.constant.email.EmailConstant;
import cn.sc.summer.constant.project.DateConstant;
import cn.sc.summer.constant.util.AssertUtil;
import cn.sc.summer.constant.util.DateUtilX;
import cn.sc.summer.exception.exceptions.CommonException;
import lombok.extern.slf4j.Slf4j;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;

import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.validation.constraints.NotNull;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 类名：  发送邮件工具类
 * 这里是非spring管理的类使用spring,ioc容器中的bean:JavaMailSender,
 * 需要 使用另一个工具类SpringUtils获取bean对象
 *
 * @author a-xin
 * @date 2023/9/28 11:32
 */
@Slf4j
@Component
public class EmailUtil {

    /**
     * velocity生成email发送的页面
     *
     * @param velocityContext velocity绑定数据
     * @param templatePath    模版路径，默认resource/email路径下
     * @return 替换好的模版信息
     */
    public static String velocityEmailText(VelocityContext velocityContext, String templatePath) {
        VelocityEngine velocityEngine = new VelocityEngine();
        velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
        velocityEngine.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
        velocityEngine.init();

        org.apache.velocity.Template mapperTemplate = velocityEngine.getTemplate("email" + templatePath, StandardCharsets.UTF_8.toString());
        StringWriter stringWriter = new StringWriter();
        mapperTemplate.merge(velocityContext, stringWriter);
        return stringWriter.toString();
    }

    /**
     * 发送邮件
     *
     * @param subject 主题
     * @param data    数据
     * @param <K>     键
     * @param <V>     值
     */
    public static <K, V> void sendEmail(String subject, Map<K, V> data) {
        VelocityContext emailTemplateParam = EmailUtil.createEmailTemplateParam(subject, data);
        String out = velocityEmailText(emailTemplateParam, "/email.html.vm");
        EmailUtil.sendComplexMail(EmailConstant.EMAIL_ADDRESS, subject, out);
    }

    /**
     * 生成邮件发送的模版参数信息
     *
     * @param subject 主题
     * @param data    数据信息
     * @param <K>     数据建
     * @param <V>     数据值
     * @return 参数集合
     */
    public static <K, V> VelocityContext createEmailTemplateParam(String subject, Map<K, V> data) {
        VelocityContext velocityContext = new VelocityContext();
        velocityContext.put(EmailConstant.TITLE, subject);
        velocityContext.put(EmailConstant.TOPIC, subject);
        velocityContext.put(EmailConstant.DATE_TIME, DateUtilX.format(new Date(), DateConstant.YYYY_MM_DD_HH_MM_SS_1));
        AssertUtil.functionIfPre(data, CollUtil::isNotEmpty, () -> velocityContext.put(EmailConstant.DATA, data));
        return velocityContext;
    }

    /**
     * 发送复杂邮件
     *
     * @param toUsers 收件人
     * @param subject 邮件标题
     * @param text    邮件内容，能够解析内容中编写的html标签。
     */
    public static void sendComplexMail(List<String> toUsers, String subject, String text) {
        log.warn("==> Start send email, The topic of the email is: {}", subject);
        // 调用SpringUtils工具类获取bean对象
        JavaMailSender javaMailSender = SpringUtil.getBean(JavaMailSender.class);
        //创建复杂邮件对象
        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        try {
            //发送复杂邮件的工具类
            //true - 能够添加附件
            MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, StandardCharsets.UTF_8.toString());
            try {
                String emailTitle = javax.mail.internet.MimeUtility.encodeText(EmailConstant.EMAIL_TITLE);
                // 发件人
                helper.setFrom(new InternetAddress(emailTitle + " <" + EmailConstant.EMAIL_FROM + ">"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
                throw new CommonException(e.getMessage(), e);
            }
            // 添加标题
            helper.setSubject(subject);
            //true - 能够再内容中编写html标签 - 会解析
            helper.setText(text, true);
            if (toUsers.size() > 1) {
                // 收件人
                helper.setTo(toUsers.get(0));
                toUsers.remove(0);
                //设置邮件抄送人，防止识别成垃圾邮件
                helper.setCc(String.join(",", toUsers));
            } else {
                helper.setTo(toUsers.get(0));
            }
            javaMailSender.send(mimeMessage);
            log.info("==> The email was sent successfully!");
        } catch (Exception e) {
            log.error("==> Email Message delivery failed：{}", mimeMessage);
            //throw new CommonException(e.getMessage(), e);
        }
    }

    /**
     * 发送简单邮件
     *
     * @param toUsers 收件人
     * @param subject 邮件标题
     * @param text    邮件内容
     */
    public static void sendSimpleMail(@NotNull List<String> toUsers, String subject, String text) {
        log.warn("==> Start send email, The topic of the email is: {}", subject);
        // 调用SpringUtils工具类获取bean对象
        JavaMailSender javaMailSender = SpringUtil.getBean(JavaMailSender.class);
        // 创建简单邮件对象
        SimpleMailMessage mailMessage = new SimpleMailMessage();
        try {
            // 发件人
            mailMessage.setFrom(EmailConstant.EMAIL_FROM);
            // 添加标题
            mailMessage.setSubject(subject);
            // 添加文本
            mailMessage.setText(text);
            if (toUsers.size() > 1) {
                // 收件人
                mailMessage.setTo(toUsers.get(0));
                toUsers.remove(0);
                //设置邮件抄送人，防止识别成垃圾邮件
                mailMessage.setCc(String.join(",", toUsers));
            } else {
                mailMessage.setTo(toUsers.get(0));
            }
            javaMailSender.send(mailMessage);
            log.info("==> The email was sent successfully!");
        } catch (MailException e) {
            log.error("==> Email Message delivery failed：{}", mailMessage);
            //throw new CommonException(e.getMessage(), e);
        }
    }
}
